package com.ybw.redis.distributed.lock.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Map;

/**
 * http工具类
 * @ClassName: HttpUtils
 * @Description:
 * @author weiyb
 * @date 2017年4月20日 上午10:30:45
 */
@Slf4j
public class HttpUtils {
	private static PoolingHttpClientConnectionManager cm;
	private static String EMPTY_STR = "";
	private static String UTF_8 = "UTF-8";

	private static void init() {
		if (cm == null) {
			cm = new PoolingHttpClientConnectionManager();
			cm.setMaxTotal(50);// 整个连接池最大连接数
			cm.setDefaultMaxPerRoute(5);// 每路由最大连接数，默认值是2
		}
	}

	/**
	 * 通过连接池获取HttpClient
	 * @return
	 * @author ybw
	 */
	public static CloseableHttpClient getHttpClient() {
		init();
		return HttpClients.custom().setConnectionManager(cm).build();
	}

	/**
	 * 处理GET请求
	 * @param url
	 * @return
	 * @author ybw
	 */
	public static String doGet(String url) {
		HttpGet httpGet = new HttpGet(url);
		return getResult(httpGet);
	}

	/**
	 * 处理GET请求
	 * @param url
	 * @param params url参数
	 * @return
	 * @throws URISyntaxException
	 * @author ybw
	 */
	public static String doGet(String url, Map<String, Object> params) throws URISyntaxException {
		URIBuilder ub = new URIBuilder(url);

		ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
		ub.setParameters(pairs);

		HttpGet httpGet = new HttpGet(ub.build());
		return getResult(httpGet);
	}

	/**
	 * 处理GET请求
	 * @param url
	 * @param headers header参数
	 * @param params url参数
	 * @return
	 * @throws URISyntaxException
	 * @author ybw
	 */
	public static String doGet(String url, Map<String, Object> headers, Map<String, Object> params)
			throws URISyntaxException {
		URIBuilder ub = new URIBuilder(url);

		ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
		ub.setParameters(pairs);

		HttpGet httpGet = new HttpGet(ub.build());
		for (Map.Entry<String, Object> param : headers.entrySet()) {
			httpGet.addHeader(param.getKey(), String.valueOf(param.getValue()));
		}
		return getResult(httpGet);
	}

	/**
	 * 处理POST请求
	 * @param url
	 * @return
	 * @author ybw
	 */
	public static String doPost(String url) {
		HttpPost httpPost = new HttpPost(url);
		return getResult(httpPost);
	}

	/**
	 * 处理POST请求
	 * @param url url参数
	 * @param params url参数
	 * @return
	 * @throws UnsupportedEncodingException
	 * @author ybw
	 */
	public static String doPost(String url, Map<String, Object> params) throws UnsupportedEncodingException {
		HttpPost httpPost = new HttpPost(url);
		ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
		httpPost.setEntity(new UrlEncodedFormEntity(pairs, UTF_8));
		return getResult(httpPost);
	}

	/**
	 * 处理POST请求
	 * @param url url参数
	 * @param headers header参数
	 * @param params url参数
	 * @return
	 * @throws UnsupportedEncodingException
	 * @author ybw
	 */
	public static String doPost(String url, Map<String, Object> headers, Map<String, Object> params)
			throws UnsupportedEncodingException {
		HttpPost httpPost = new HttpPost(url);

		for (Map.Entry<String, Object> param : headers.entrySet()) {
			httpPost.addHeader(param.getKey(), String.valueOf(param.getValue()));
		}

		ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
		httpPost.setEntity(new UrlEncodedFormEntity(pairs, UTF_8));

		return getResult(httpPost);
	}

	/**
	 * 处理POST请求,提交json数据
	 * @param url url参数
	 * @param json json参数
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 * @author ybw
	 */
	public static String doPostJson(String url, String json) {
		// 创建http POST请求
		HttpPost httpPost = new HttpPost(url);
		if (StringUtils.isNotBlank(json)) {
			// 构造一个请求实体
			StringEntity stringEntity = new StringEntity(json, ContentType.APPLICATION_JSON);
			// 将请求实体设置到httpPost对象中
			httpPost.setEntity(stringEntity);
		}
		return getResult(httpPost);
	}

	/**
	 * 处理POST请求,提交json数据
	 * @param url url参数
	 * @param headers header参数
	 * @param json json参数
	 * @return
	 * @author ybw
	 */
	public static String doPostJson(String url, Map<String, Object> headers, String json) {
		// 创建http POST请求
		HttpPost httpPost = new HttpPost(url);
		
		for (Map.Entry<String, Object> param : headers.entrySet()) {
			httpPost.addHeader(param.getKey(), String.valueOf(param.getValue()));
		}
		
		if (StringUtils.isNotBlank(json)) {
			// 构造一个请求实体
			StringEntity stringEntity = new StringEntity(json, ContentType.APPLICATION_JSON);
			// 将请求实体设置到httpPost对象中
			httpPost.setEntity(stringEntity);
		}
		return getResult(httpPost);
	}

	/**
	 * map转为ArrayList<NameValuePair>
	 * @param params
	 * @return
	 * @author ybw
	 */
	public static ArrayList<NameValuePair> covertParams2NVPS(Map<String, Object> params) {
		ArrayList<NameValuePair> pairs = new ArrayList<NameValuePair>();
		for (Map.Entry<String, Object> param : params.entrySet()) {
			pairs.add(new BasicNameValuePair(param.getKey(), String.valueOf(param.getValue())));
		}
		return pairs;
	}

	/**
	 * 处理Http请求，返回结果
	 * @param request
	 * @return
	 * @author ybw
	 */
	private static String getResult(HttpRequestBase request) {
		CloseableHttpClient httpClient = getHttpClient();
		try {
			CloseableHttpResponse response = httpClient.execute(request);
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				String result = EntityUtils.toString(entity);
				response.close();
				return result;
			}
		} catch (ClientProtocolException e) {
			log.error("处理Http请求报错:", e);
		} catch (IOException e) {
			log.error("处理Http请求报错:", e);
		}
		return EMPTY_STR;
	}
	
	/**
	 * 获取ip地址
	 * @param request
	 * @return
	 * @author weiyb
	 */
	public static String getIp(HttpServletRequest request) {
		String ip = request.getHeader("X-Forwarded-For");
		if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
			// 多次反向代理后会有多个ip值，第一个ip才是真实ip
			int index = ip.indexOf(",");
			if (index != -1) {
				return ip.substring(0, index);
			} else {
				return ip;
			}
		}
		ip = request.getHeader("X-Real-IP");
		if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
			return ip;
		}
		return request.getRemoteAddr();
	}

}